import React, {useState} from "react";
import {Animated, Image, StyleSheet, Text, useWindowDimensions, View} from "react-native";
import RootSiblingsManager from "react-native-root-siblings";

const TOAST_MAX_WIDTH = 0.8;
const TOAST_ANIMATION_DURATION = 200;
export const positions = {
    TOP: 20,
    BOTTOM: -20,
    CENTER: 0
};
export const durations = {
    LONG: 3500,
    SHORT: 2000
};

const styles = StyleSheet.create({
    container: {
        position: "absolute",
        alignItems: "center",
        justifyContent: "center",
        zIndex: 9999
    },
    toast: {
        padding: 15,
        borderRadius: 5,
        backgroundColor: "#000",
        alignItems: "center",
        justifyContent: "center"
    },
    shadow: {
        shadowColor: "#000",
        shadowOffset: {
            width: 4,
            height: 4
        },
        shadowOpacity: 0.8,
        shadowRadius: 6,
        elevation: 10
    },
    text: {
        fontSize: 16,
        color: "#fff",
        textAlign: "center"
    }
});

type ToastContainerProps = {
    text?: string,
    type?: string,
    position?: number,
};
const ToastContainer = (props: ToastContainerProps) => {
    const dimensions = useWindowDimensions();
    const [opacity, setOpacity] = useState(new Animated.Value(0));
    const {
        text,
        type,
        position = positions.CENTER
    } = props;

    const getContainerStyle = () => {
        const margin = (dimensions.width * (1 - TOAST_MAX_WIDTH)) / 2;
        const style: any = {
            left: margin,
            right: margin
        };

        if (position === positions.TOP) {
            style.top = "20%";
        } else if (position === positions.BOTTOM) {
            style.bottom = "20%";
        } else {
            style.top = "45%";
        }

        return style;
    };

    const renderIcon = () => {
        let icon;
        if (type === "success") {
            icon = require("./assets/success.png");
        } else if (type === "error") {
            icon = require("./assets/fail.png");
        }

        if (icon) {
            return (
                <View style={StyleSheet.flatten({
                    justifyContent: "center",
                    alignItems: "center",
                    marginBottom: 10,
                    minWidth: 200
                })}>
                    <Image
                        source={icon}
                        style={{
                            width: 40,
                            height: 40,
                            tintColor: "#fff"
                        }}
                    />
                </View>
            );
        } else {
            return null;
        }
    };

    React.useLayoutEffect(() => {
        Animated.timing(opacity, {
            toValue: 1,
            duration: TOAST_ANIMATION_DURATION,
            useNativeDriver: true
        }).start();
    }, []);

    return (
        <View style={[
            styles.container,
            getContainerStyle()
        ]}>
            <Animated.View
                style={[
                    styles.toast,
                    {
                        maxWidth: TOAST_MAX_WIDTH * dimensions.width,
                        opacity: opacity
                    }
                ]}
            >
                {renderIcon()}
                <Text style={styles.text}>{text}</Text>
            </Animated.View>
        </View>
    );
};

class ToastClass {
    static sibling: any = null;
    static timer: any = null;

    static show = (options: ToastOptions) => {
        const {
            duration: duration = durations.LONG
        } = options;

        if (this.sibling) {
            this.sibling.update(
                <ToastContainer
                    text={options.message}
                    type={options.type}
                    position={options.position}
                />
            );
        } else {
            this.sibling = new RootSiblingsManager(
                <ToastContainer
                    text={options.message}
                    type={options.type}
                    position={options.position}
                />
            );
        }
        options?.onShow?.();

        if (this.timer) clearTimeout(this.timer);
        this.timer = setTimeout(() => {
            this.sibling.destroy();
            this.sibling = null;
            options?.onHide?.();
        }, duration);
    };
}

export type ToastOptions = {
    message?: string,
    duration?: number,
    position?: number,
    type?: string,
    shadow?: boolean,
    onShow?: () => void,
    onHide?: () => void,
}


const message = (text?: string, options?: ToastOptions) => {
    return ToastClass.show({
        message: text,
        ...options
    });
};

const success = (text?: string, options?: ToastOptions) => {
    return message(text, {
        type: "success",
        ...options
    });
};

const error = (text?: string, options?: ToastOptions) => {
    return message(text, {
        type: "error",
        ...options
    });
};


export default {
    message,
    success,
    error,
    fail: error
};
